/**
 * python 2 c/api doc
 * https://docs.python.org/2/c-api/index.html
 */

#include <python/Python.h>
#include <stdio.h>

/*****************c extend python module************************/
/*https://docs.python.org/2/extending/index.html*/
/*
    类似python代码： kify.py
    import os
    def system(cmd):
        res = os.system(cmd)
        return res
 */
static PyObject * spam_system(PyObject *self, PyObject *args)
{
    const char *command;
    int sts;

    if (!PyArg_ParseTuple(args, "s", &command))
        return NULL;
    sts = system(command);
    return Py_BuildValue("i", sts);
}

static PyMethodDef SpamMethods[] = {
    // ...
    {"system",  spam_system, METH_VARARGS, "Execute a shell command."},
    // ...
    {NULL, NULL, 0, NULL}        /* Sentinel */
};

PyMODINIT_FUNC init_cextend_modules(void)
{
    // 初始化模块
    (void) Py_InitModule("spam", SpamMethods);
}

/*****************c extend python module end************************/

static void check_exception()
{
    // 异常检查处理
    /**
     * exception: https://docs.python.org/2/c-api/exceptions.html
     * PyObject* PyErr_Occurred()
     * void PyErr_Print()
     */
    if (PyErr_Occurred()) {
        // 输出异常信息
        PyErr_Print();
    }
}

int main(int argc, char **argv)
{
    // 初始化python上下文环境
    Py_Initialize();
    // 将命令行参数传递到python sys.argv中
    PySys_SetArgv(argc, argv);

    // 初始化c扩展python模块
    init_cextend_modules();

    PyObject* pModule = NULL;
    PyObject* pFunc = NULL;
    PyObject* pParam = NULL;
    PyObject* pResult = NULL;
    const char* pBuffer = NULL;
    int iBufferSize = 0;


    // 导入一个python 模块 mytest
    pModule = PyImport_ImportModule("mytest");
    if (!pModule) {
        printf("get module failed!\n");
        check_exception();
        exit (0);
    }

    // 获取mytest模块中的main函数
    pFunc = PyObject_GetAttrString(pModule, "main");
    if (!pFunc) {
        printf("get func failed!\n");
        check_exception();
        exit (0);
    }

    /**
     * PyArg_Parse : https://docs.python.org/2/c-api/arg.html
     * PyObject* Py_BuildValue(const char *format, ...)
     *
     * Create a new value based on a format string similar to those
     * accepted by the PyArg_Parse*() family of functions and
     * a sequence of values. Returns the value or NULL in the case of an error;
     * an exception will be raised if NULL is returned.
     *
     * 不一定创建一个tupple变量，当有多个时才会创建
     */
    // 创建一个字符串python变量
    pParam = Py_BuildValue("(s)", "HEHEHE");

    // 执行mytest.main函数
    pResult = PyEval_CallObject(pFunc, pParam);
    if (pResult) {
        /**
         * PyArg_Parse : https://docs.python.org/2/c-api/arg.html
         * format type: s: const char *, i: int, ..., b, h, ...
         * int PyArg_ParseTuple(PyObject *args, const char *format, ...)
         * int PyArg_Parse(PyObject *args, const char *format, ...)
         *
         * Parse the parameters of a function that takes only positional
         * parameters into local variables.
         * Returns true on success; on failure, it returns false and
         * raises the appropriate exception.
         */
        if (PyArg_Parse(pResult, "(si)", &pBuffer, &iBufferSize)) {
            printf("%s\n", pBuffer);
            printf("%d\n", iBufferSize);
        }
    } else {
        check_exception();
    }


    Py_DECREF(pParam);
    Py_DECREF(pFunc);
    Py_Finalize();
    printf("======\n");
    return 0;
}

